package com.lanyun.carworld.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lanyun.carworld.common.ErrorCode;
import com.lanyun.carworld.config.JwtConfig;
import com.lanyun.carworld.constant.JwtClaimsConstant;
import com.lanyun.carworld.constant.UserConstant;
import com.lanyun.carworld.context.BaseContext;
import com.lanyun.carworld.exception.BusinessException;
import com.lanyun.carworld.model.dto.user.ChangePasswordRequest;
import com.lanyun.carworld.model.dto.user.UserLoginRequest;
import com.lanyun.carworld.model.dto.user.UserRegisterRequest;
import com.lanyun.carworld.model.dto.user.UserSearchRequest;
import com.lanyun.carworld.model.entity.User;
import com.lanyun.carworld.mapper.UserMapper;
import com.lanyun.carworld.model.vo.LoginUserVO;
import com.lanyun.carworld.model.vo.UserVO;
import com.lanyun.carworld.service.UserRoleService;
import com.lanyun.carworld.service.UserService;
import com.lanyun.carworld.utils.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* @author 29074
* @description 针对表【user(用户)】的数据库操作Service实现
* @createDate 2024-06-11 15:22:43
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{


    /**
     * 盐值，混淆密码
     */
    private static final String SALT = "lanyun";

    @Resource
    private JwtConfig jwtProperties;


    @Resource
    private UserRoleService userRoleService;

    /**
     * 用户注册
     * @param request
     * @return
     */
    @Override
    public Boolean userRegister(UserRegisterRequest request) {
        String userAccount = request.getUserAccount();
        String userPassword = request.getUserPassword();
        String checkPassword = request.getCheckPassword();
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword, checkPassword)) {

            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");

        }
        if (userAccount.length() < 4) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户账号过短");

        }
        if (userPassword.length() < 8 || checkPassword.length() < 8) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户密码过短");

        }
        // 密码和校验密码相同
        if (!userPassword.equals(checkPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致");
        }

        // 账户不能重复
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        User user1 = this.baseMapper.selectOne(queryWrapper);

        if (user1 != null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号重复");
        }

        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 3. 插入数据
        User user = new User();
        user.setUserAccount(userAccount);
        user.setUserPassword(encryptPassword);
        boolean saveResult = save(user);

        return saveResult;
    }


    /**
     * 用户登录
     * @param request
     * @return
     */
    @Override
    public LoginUserVO userLogin(UserLoginRequest request) {
        String userAccount = request.getUserAccount();
        String userPassword = request.getUserPassword();
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        boolean flag1,flag2;


        flag1 = userAccount.matches("20[0-9]{8}");


        flag2 = userPassword.matches("^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{6,18}$");

        if (!flag1 || !flag2) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号或密码错误");
        }


        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 查询用户是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("userAccount", userAccount);
        queryWrapper.eq("userPassword", encryptPassword);
        User user = this.baseMapper.selectOne(queryWrapper);
        // 用户不存在
        if (user == null) {
            log.info("user login failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        }

        if(user.getUserRole().equals(UserConstant.BAN_ROLE)){
            //用户被禁用
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "用户被禁用");
        }


        //分配了角色没
        Long userId = user.getId();
        userRoleService.checkUserRole(userId);


        Map<String,Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID,user.getId());
        String userSecretKey = jwtProperties.getUserSecretKey();
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);
        System.out.println(token);




        // 3. 返回用户信息
        LoginUserVO loginUserVO = LoginUserVO.builder()
                .id(user.getId())
                .token(token)
                .build();
        return loginUserVO;
    }

    /**
     * 获取用户信息
     * @return
     */
    @Override
    public UserVO getUserInfo() {
        // 1. 获取用户信息
        User user = getCurrentUser();
        // 2. 返回用户信息
        UserVO userVO = UserVO.builder()
                .userAvatar(user.getUserAvatar())
                .gender(user.getGender())
                .userName(user.getUserName())
                .userProfile(user.getUserProfile())
                .userEmail(user.getUserEmail())
                .userPhone(user.getUserPhone())
                .build();
        return userVO;
    }


    /**
     * 更新用户信息
     * @param userVO
     * @return
     */
    @Override
    public Boolean updateUserInfo(UserVO userVO) {
        // 1. 获取用户信息
        User user = getCurrentUser();
        // 2. 更新用户信息
        user.setUserAvatar(userVO.getUserAvatar());
        user.setGender(userVO.getGender());
        user.setUserName(userVO.getUserName());
        user.setUserProfile(userVO.getUserProfile());
        user.setUserEmail(userVO.getUserEmail());
        user.setUserPhone(userVO.getUserPhone());
        user.setUpdateTime(new Date());
        boolean updateResult = updateById(user);
        return updateResult;

    }

    /**
     * 确定账号和密码是否正确
     * @param request
     * @return
     */
    @Override
    public Boolean predefinePassword(UserLoginRequest request) {
        String userAccount = request.getUserAccount();
        String userPassword = request.getUserPassword();
        // 1. 校验
        if (StringUtils.isAnyBlank(userAccount, userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空");
        }

        boolean flag1,flag2;


        flag1 = userAccount.matches("20[0-9]{8}");


        flag2 = userPassword.matches("^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{6,18}$");

        if (!flag1 || !flag2) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "账号或密码错误");
        }


        // 2. 加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        // 查询用户

        User user = getCurrentUser();
        // 用户不存在
        if (user == null) {
            log.info("user login failed, userAccount cannot match userPassword");
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "用户不存在或密码错误");
        }

        if(user.getUserRole().equals(UserConstant.BAN_ROLE)){
            //用户被禁用
            throw new BusinessException(ErrorCode.FORBIDDEN_ERROR, "用户被禁用");
        }

        //判断是否正确
        if (!user.getUserPassword().equals(encryptPassword) || !user.getUserAccount().equals(userAccount)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "输入的账号或密码错误");
        }

        return true;

    }


    /**
     * 修改密码
     * @param request
     * @return
     */
    @Override
    public Boolean modifyPassword(ChangePasswordRequest request) {

        String okUserPassword = request.getOkUserPassword();
        String userPassword = request.getUserPassword();

        //判断是否一样
        if (!okUserPassword.equals(userPassword)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "两次输入的密码不一致，修改失败");
        }

        //判断密码是否合法
        boolean flag = userPassword.matches("^(?![a-zA-Z]+$)(?!\\d+$)(?![^\\da-zA-Z\\s]+$).{6,18}$");
        if (!flag) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "密码不符合要求，修改失败");
        }


        //加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes());

        //获取用户信息
        User user = getCurrentUser();

        //更新密码
        user.setUserPassword(encryptPassword);
        user.setUpdateTime(new Date());


        boolean updateResult = updateById(user);
        return updateResult;

    }

    /**
     * 获取用户列表
     * @param request
     * @return
     */
    @Override
    public List<UserVO> getUserList(UserSearchRequest request) {
        String searchNum = request.getSearchNum();
        Integer pageSize = request.getPageSize();
        Integer pageNum = request.getPageNum();

        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        //分页查询
        Page<User> page = new Page<>(pageNum, pageSize);
        queryWrapper.like(StringUtils.isNotBlank(searchNum), "user_account", searchNum);

        queryWrapper.eq("userRole", UserConstant.DEFAULT_ROLE);


        List<User> userList = this.baseMapper.selectPage(page, queryWrapper).getRecords();

        List<UserVO> userVOList = UserVO.convertEntityList(userList);

        return userVOList;
    }


    private User getCurrentUser() {
        Long userId = BaseContext.getCurrentId();
        if (userId == null) {
            throw new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "用户未登录");
        }
        // 4. 查询用户信息
        User user = this.getById(userId);
        return user;
    }



}




